require 'chess-data'
require 'minitest/autorun'

describe ChessData::Game do
  it "correctly reads a test file" do
    File.open "test/data/fischer.pgn" do |file|
      game = ChessData::Game.from_pgn file
      _(game.event).must_equal "F/S Return Match"
      _(game.site).must_equal "Belgrade, Serbia JUG"
      _(game.date).must_equal "1992.11.04"
      _(game.round).must_equal "29"
      _(game.white).must_equal "Fischer, Robert J."
      _(game.black).must_equal "Spassky, Boris V."
      _(game.half_moves).must_equal 85
      _(game.start_position).must_equal ChessData::Board.start_position
    end
  end

  it "correctly uses a given fen as start position" do
    File.open "test/data/games4.pgn" do |file|
      game = ChessData::Game.from_pgn file
      _(game.start_position).must_equal \
        ChessData::Board.from_fen "r3k2r/1bqn1p1p/p1n1pb1Q/1p6/3N1P2/2N1B3/PPP1B1PP/3R1R1K b kq - 0 18"
    end
  end

  it "adds moves either of a move-class, or as a string" do
    game = ChessData::Game.new
    game << ChessData::Moves.new_move("e4")
    game << "e6"
    _(game.half_moves).must_equal 2
    _(game.moves[0].class).must_equal ChessData::Moves::SimplePawnMove
    _(game.moves[0].to_s).must_equal "e4"
    _(game.moves[1].class).must_equal ChessData::Moves::SimplePawnMove
    _(game.moves[1].to_s).must_equal "e6"
    assert_raises(ChessData::InvalidMoveError) { game << "rnd" }    
    assert_raises(ChessData::InvalidMoveError) { game << ChessData::Board.start_position }
  end

  def check_move start, move, final
    board = ChessData::Moves.new_move(move).make_move ChessData::Board.from_fen start
    _(board).must_equal ChessData::Board.from_fen(final), "testing move #{move}"
  end

  it "manages moves" do
    [ # castling moves
      ["8/8/8/8/8/8/8/4K2R w K - 0 0", "O-O", "8/8/8/8/8/8/8/5RK1 b - - 1 0"],
      ["4k2r/8/8/8/8/8/8/8 b k - 0 0", "O-O", "5rk1/8/8/8/8/8/8/8 w - - 1 1"],
      ["8/8/8/8/8/8/8/R3K2R w KQ - 0 0", "O-O-O", "8/8/8/8/8/8/8/2KR3R b - - 1 0"],
      ["r3k2r/8/8/8/8/8/8/8 b kq - 0 0", "O-O-O", "2kr3r/8/8/8/8/8/8/8 w - - 1 1"],
      # simple pawn moves
      ["rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", "e4", 
        "rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1"],
      ["rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1", "a3", 
        "rnbqkbnr/pppppppp/8/8/8/P7/1PPPPPPP/RNBQKBNR b KQkq - 0 1"],
      ["8/8/4P3/8/8/8/8/8 w - - 10 23", "e7", "8/4P3/8/8/8/8/8/8 b - - 0 23"],
      ["rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1", "d5", 
        "rnbqkbnr/ppp1pppp/8/3p4/4P3/8/PPPP1PPP/RNBQKBNR w KQkq d6 0 2"],
      ["rnbqkbnr/pppppppp/8/8/4P3/8/PPPP1PPP/RNBQKBNR b KQkq e3 0 1", "g6",
       "rnbqkbnr/pppppp1p/6p1/8/4P3/8/PPPP1PPP/RNBQKBNR w KQkq - 0 2"],
      ["8/8/8/8/8/2p5/8/8 b - - 10 23", "c2", "8/8/8/8/8/8/2p5/8 w - - 0 24"],
      # pawn promotions
      ["8/4P3/8/8/8/8/8/8 w - - 10 23", "e8=Q", "4Q3/8/8/8/8/8/8/8 b - - 0 23"],
      ["8/4P3/8/8/8/8/8/8 w - - 10 23", "e8=N", "4N3/8/8/8/8/8/8/8 b - - 0 23"],
      ["8/8/8/8/8/8/2p5/8 b - - 10 23", "c1=B", "8/8/8/8/8/8/8/2b5 w - - 0 24"],
      ["7k/4P3/8/8/8/8/8/8 w - - 10 23", "e8=Q+", "4Q2k/8/8/8/8/8/8/8 b - - 0 23"],
      # piece moves
      ["8/8/8/8/4Q3/8/8/8 w - - 10 23", "Qe8", "4Q3/8/8/8/8/8/8/8 b - - 11 23"],
      ["4q3/8/8/8/4Q3/8/8/8 w - - 10 23", "Qxe8", "4Q3/8/8/8/8/8/8/8 b - - 0 23"],
      ["8/8/8/8/4r3/8/8/8 b - - 10 23", "Rh4", "8/8/8/8/7r/8/8/8 w - - 11 24"],
      ["8/8/8/8/Pr3/8/8/8 b - - 10 23", "Rxa4", "8/8/8/8/r7/8/8/8 w - - 0 24"],
      ["8/8/5p2/8/4N3/8/8/8 w - - 10 23", "Nxf6", "8/8/5N2/8/8/8/8/8 b - - 0 23"],
      ["8/8/5p2/8/4k3/8/8/8 b - - 10 23", "Kd5", "8/8/5p2/3k4/8/8/8/8 w - - 11 24"],
      ["8/8/8/8/1N3N2/8/8/8 w - - 10 23", "Nbd5", "8/8/8/3N4/5N2/8/8/8 b - - 11 23"],
      ["8/8/8/8/1N3N2/8/8/8 w - - 10 23", "Nfd5", "8/8/8/3N4/1N6/8/8/8 b - - 11 23"],
      ["8/8/8/8/1R6/1p6/8/1R6 w - - 10 23", "R1xb3", "8/8/8/8/1R6/1R6/8/8 b - - 0 23"],
      ["8/8/8/8/1R6/1p6/8/1R6 w - - 10 23", "R4xb3", "8/8/8/8/8/1R6/8/1R6 b - - 0 23"],
      ["r1bqk2r/1pppbppp/p1n2n2/4p3/B3P3/5N2/PPPP1PPP/RNBQ1RK1 w - - 2 6", "Re1",
        "r1bqk2r/1pppbppp/p1n2n2/4p3/B3P3/5N2/PPPP1PPP/RNBQR1K1 b - - 3 6"],
      ["Q7/8/2p5/8/8/8/8/7Q w - - 10 23", "Qf3", "Q7/8/2p5/8/8/5Q2/8/8 b - - 11 23"],
      ["r2q1rk1/1b1nbppp/2pp1n2/1p2p3/3PP3/1BN2N1P/PP3PP1/R1BQR1K1 w - - 0 14",
        "Bg5",
        "r2q1rk1/1b1nbppp/2pp1n2/1p2p1B1/3PP3/1BN2N1P/PP3PP1/R2QR1K1 b - - 1 14"],
      ["r2q1rk1/1b1nbpp1/3p3p/2p1P3/1p2n2B/1B3N1P/PP3PP1/RN1QR1K1 w - - 0 18",
        "Bxe7",
        "r2q1rk1/1b1nBpp1/3p3p/2p1P3/1p2n3/1B3N1P/PP3PP1/RN1QR1K1 b - - 0 18"],
      ["8/8/8/8/1b6/2N5/8/4K1N1 w - - 0 10",
        "Ne2",
        "8/8/8/8/1b6/2N5/4N3/4K3 b - - 1 10"],
      # Pawn captures
      ["8/8/8/3p4/4P3/8/8/8 w - - 10 23", "exd5", "8/8/8/3P4/8/8/8/8 b - - 0 23"],
      ["8/8/8/3p4/4P3/8/8/8 b - - 10 23", "dxe4", "8/8/8/8/4p3/8/8/8 w - - 0 24"],
      ["8/8/8/8/3pP3/8/8/8 b - e3 10 23", "dxe3", "8/8/8/8/8/4p3/8/8 w - - 0 24"],
      ["8/8/8/3pP3/8/8/8/8 w - d6 10 23", "exd6", "8/8/3P4/8/8/8/8/8 b - - 0 23"],
      ["3n4/4P3/8/8/8/8/8/8 w - - 10 23", "exd8=B", "3B4/8/8/8/8/8/8/8 b - - 0 23"]
    ].each do |defn| 
      check_move defn[0], defn[1], defn[2]
    end
  end

end

